﻿#include "../ctlStatic.h"
#include "../ctlCheckBox.h"
#include "../ctlRadioBox.h"
#include "../ctlButton.h"
#include "../ctlImageButton.h"

namespace swui
{
	static inline bool is_inRect(const ctlRect& rect, const ctlPoint& point)
	{
		return (rect.x <= point.x && rect.x + rect.cx >= point.x
			&& rect.y <= point.y && rect.y + rect.cy >= point.y);
	}
	template<typename T>
	static inline T intPow2(T value)
	{
		return value * value;
	}
	static inline bool inCircle(const ctlPoint& pt, const ctlPoint &center, int radius)
	{
		return intPow2(pt.x - center.x) + intPow2(pt.y - center.y) <= intPow2(radius);
	}

	bool IRound::_judge_point_(ctlPoint pt)
	{
		if(isRoundEnabled() == false)
			return is_inRect(_rect, pt);
		if(!is_inRect(_rect, pt)) return false;
		pt.x -= getLeft(), pt.y -= getTop();
		int radius = (int)getRoundRadius();
		int halfr = ctlMin(getWidth(), getHeight()) / 2;
		if(radius > halfr) radius = halfr;
		if((unsigned)getRoundDirection() & (unsigned)ctlRoundDirection::leftTop)
		{
			if(pt.x <= radius && pt.y <= radius &&
				!inCircle(pt, ctlPoint(radius, radius), radius)) return false;
		}
		if((unsigned)getRoundDirection() & (unsigned)ctlRoundDirection::leftBottom)
		{
			if(pt.x <= radius && pt.y >= getHeight() - radius &&
				!inCircle(pt, ctlPoint(radius, getHeight() - radius), radius)) return false;
		}
		if((unsigned)getRoundDirection() & (unsigned)ctlRoundDirection::rightBottom)
		{
			if(pt.x >= getWidth() - radius && pt.y >= getHeight() - radius &&
				!inCircle(pt, ctlPoint(getWidth() - radius, getHeight() - radius), radius)) return false;
		}
		if((unsigned)getRoundDirection() & (unsigned)ctlRoundDirection::rightTop)
		{
			if(pt.x >= getWidth() - radius && pt.y <= radius &&
				!inCircle(pt, ctlPoint(getWidth() - radius, radius), radius)) return false;
		}
		return true;
	}

	bool ctlStatic::_judge_point_(ctlPoint pt)
	{
		if(!isNotify() || !isEnabled()) return false;
		return is_inRect(_rect, pt);
	}

	bool ctlRoot::_judge_point_(ctlPoint pt)
	{
		if(!isEnabled()) return false;
		return is_inRect(_rect, pt);
	}

	bool ctlCheckBox::_judge_point_(ctlPoint pt)
	{
		if(!isEnabled()) return false;
		if(is_inRect(_getBoxRect(), pt))
			return true;
		return is_inRect(ctlRect(getLeft() + ctlCheckBox::BoxWidth, getTop(), 
			getWidth() - ctlCheckBox::BoxWidth, getHeight()), pt);
	}

	bool ctlRadioBox::_judge_point_(ctlPoint pt)
	{
		if(!isEnabled()) return false;
		ctlRect rect = _getBoxRect();
		float radius = rect.cx / 2.0f;
		float ox = intPow2(rect.x + radius - pt.x);
		float oy = intPow2(rect.y + radius - pt.y);
		if(ox + oy <= radius * radius)
			return true;
		return is_inRect(ctlRect(getLeft() + ctlCheckBox::BoxWidth, getTop(), 
			getWidth() - ctlCheckBox::BoxWidth, getHeight()), pt);
	}
	
	bool ctlImageButton::_judge_point_(ctlPoint pt)
	{
		if(!isEnabled()) return false;
		if(!is_inRect(_rect, pt)) return false;
		std::shared_ptr<ctlImage> img = getLeaveImage();
		if(img.get() == nullptr) return false;
		pt.x -= getLeft(), pt.y -= getTop();
		if(isScaleImage())
		{
			pt.x *= img->getWidth();
			pt.x /= getWidth();
			pt.y *= img->getHeight();
			pt.y /= getHeight();
		}
		if(img->isMatrixEnabled())
		{
			float f[6];
			img.get()->getNativeMatrix()->GetElements(f);
			ctlPoint pg;
			float p_base = f[1] * f[2] -  f[0] * f[3];
			pg.x = static_cast<int>((f[3] * f[4] - f[2] * f[5] - 
				f[3] * pt.x + f[2] * pt.y) / p_base);
			pg.y = -static_cast<int>((f[1] * f[4] - f[0] * f[5] - 
				f[1] * pt.x + f[0] * pt.y) / p_base);
			pt = pg;
			if(!is_inRect(ctlRect(0,  0, img->getWidth(), img->getHeight()), pt))
				return false;
		}
		if(pt.x >= (int)img->getWidth()
			|| pt.y >= (int)img->getHeight()) 
			return false;
		ctlColor cr = img->getColor(pt);
		if(img->isColor24())
		{
			if(hasMask() == false) return true;
			if((cr & 0xffffff) == (getMaskColor() & 0xffffff))
				return false;
		} else {
			if((cr >> 24) <= getJudgeAlpha())
				return false;
			if(hasMask() && cr == getMaskColor())
				return false;
		}
		return true;
	}
}
